home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / mesa / mesa-glut / src-glut.aos / glutmainloop.c < prev    next >
C/C++ Source or Header  |  2000-02-23  |  14KB  |  456 lines

  1. /*
  2.  * Amiga GLUT graphics library toolkit
  3.  * Version:  1.1
  4.  * Copyright (C) 1998 Jarno van der Linden
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Library General Public
  17.  * License along with this library; if not, write to the Free
  18.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * glutMainLoop.c
  23.  *
  24.  * Version 1.0  27 Jun 1998
  25.  * by Jarno van der Linden
  26.  * jarno@kcbbs.gen.nz
  27.  *
  28.  */
  29.  
  30. extern struct ExecBase *SysBase;
  31. #include <inline/intuition.h>
  32. #include <inline/gadtools.h>
  33. #include <inline/exec.h>
  34. #include <inline/dos.h>
  35. #include <inline/graphics.h>
  36. #include <inline/layers.h>
  37. #include <libraries/gadtools.h>
  38.  
  39. #include <stdlib.h>
  40.  
  41. #include "glutstuff.h"
  42.  
  43. extern void RedoMenu(int button, struct GlutMenu *glutmenu);
  44.  
  45. static int ConvRaw(UWORD code, UWORD qual)
  46. {
  47.   switch (code) {
  48.     case CURSORLEFT:
  49.       return GLUT_KEY_LEFT;
  50.     case CURSORUP:
  51.       return GLUT_KEY_UP;
  52.     case CURSORRIGHT:
  53.       return GLUT_KEY_RIGHT;
  54.     case CURSORDOWN:
  55.       return GLUT_KEY_DOWN;
  56.     case 0x50:
  57.       return GLUT_KEY_F1;
  58.     case 0x51:
  59.       return GLUT_KEY_F2;
  60.     case 0x52:
  61.       return GLUT_KEY_F3;
  62.     case 0x53:
  63.       return GLUT_KEY_F4;
  64.     case 0x54:
  65.       return GLUT_KEY_F5;
  66.     case 0x55:
  67.       return GLUT_KEY_F6;
  68.     case 0x56:
  69.       return GLUT_KEY_F7;
  70.     case 0x57:
  71.       return GLUT_KEY_F8;
  72.     case 0x58:
  73.       return GLUT_KEY_F9;
  74.     case 0x59:
  75.       return GLUT_KEY_F10;
  76.   }
  77.  
  78.   return code;
  79. }
  80.  
  81. static int ConvToButton(UWORD code, UWORD qual)
  82. {
  83.   switch (code) {
  84.     case SELECTUP:
  85.     case SELECTDOWN:
  86.       if (qual & IEQUALIFIER_RCOMMAND)
  87.     return GLUT_MIDDLE_BUTTON;
  88.       if (qual & IEQUALIFIER_RALT)
  89.     return GLUT_RIGHT_BUTTON;
  90.       return GLUT_LEFT_BUTTON;
  91.     case MIDDLEUP:
  92.     case MIDDLEDOWN:
  93.       return GLUT_MIDDLE_BUTTON;
  94.     case MENUUP:
  95.     case MENUDOWN:
  96.       return GLUT_RIGHT_BUTTON;
  97.   }
  98.  
  99.   return code;
  100. }
  101.  
  102. static int ConvToButtonState(UWORD code)
  103. {
  104.   switch (code) {
  105.     case SELECTUP:
  106.     case MIDDLEUP:
  107.     case MENUUP:
  108.       return GLUT_UP;
  109.     case SELECTDOWN:
  110.     case MIDDLEDOWN:
  111.     case MENUDOWN:
  112.       return GLUT_DOWN;
  113.   }
  114.  
  115.   return code;
  116. }
  117.  
  118. void glutMainLoop(void)
  119. {
  120.   BOOL wanttoquit = FALSE;
  121.  
  122.   while (1) {
  123.     struct GlutWindow *actWindow;
  124.     struct GlutMenu *actMenu;
  125.     struct IntuiMessage *msg;
  126.     struct Window *win;
  127.     BOOL idleing = TRUE;
  128.  
  129.     if(!glutstuff.Windows.nodes) {
  130.       DEBUGOUT(1, "no windows open to process\n");
  131.       return;
  132.     }
  133.  
  134.     /* Apply changes
  135.      */
  136.     actWindow = (struct GlutWindow *)&glutstuff.Windows;
  137.     while ((actWindow = (struct GlutWindow *)nGetNext(&actWindow->WindowNode))) {
  138.       win = actWindow->window;
  139.       stuffMakeCurrent(actWindow);
  140.  
  141.       if (actWindow->WindowTimers.nodes) {
  142.         struct GlutTimer *gt = (struct GlutTimer *)nGetHead(&actWindow->WindowTimers);
  143.  
  144.     while(gt) {
  145.       struct GlutTimer *new = (struct GlutTimer *)nGetNext(>->TimerNode);
  146.       ULONG secs, micros;
  147.  
  148.       CurrentTime(&secs, µs);                        /* better for accuracity */
  149.       if ((secs > gt->secs) || ((secs == gt->secs) && (micros > gt->micros))) {
  150.         DEBUGOUT(2, "do timer (%ld:%ld), set for (%ld:%ld)\n", secs, micros, gt->secs, gt->micros);
  151.  
  152.         idleing = FALSE;
  153.         if (gt->timerfunc)                            /* be paranoid */
  154.           (*gt->timerfunc) (gt->TimerValue);
  155.  
  156.         dRemove(&actWindow->WindowTimers, >->TimerNode);
  157.         FreeVecPooled(glutPool, (ULONG *)gt);
  158.       }
  159.       else
  160.         DEBUGOUT(2, "skip timer (%ld:%ld), wait for (%ld:%ld)\n", secs, micros, gt->secs, gt->micros);
  161.  
  162.       gt = new;
  163.     }
  164.       }
  165.  
  166.       /* Hide/Show/Iconify */                            /* TODO: workbench.library icons */
  167.       /*  then break if hide or iconify */
  168.       /*  continue if show */
  169.       if (actWindow->pop) {
  170.         WindowToFront(win);
  171.         actWindow->pop = FALSE;
  172.         actWindow->push = FALSE;
  173.       }
  174.       else if (actWindow->push) {
  175.         WindowToBack(win);
  176.         actWindow->push = FALSE;
  177.         actWindow->pop = FALSE;
  178.       }
  179.  
  180.       if (actWindow->needposition) {
  181.     actWindow->needposition = FALSE;
  182.     actWindow->needpositiongui = FALSE;
  183.     /* Let the change be made through the gui */
  184.     ChangeWindowBox(win, actWindow->winx, actWindow->winy, actWindow->winwidth, actWindow->winheight);
  185.     actWindow->fullscreen = FALSE;        /* BUG?: could prevent fullscreen-mode */
  186.       }
  187.  
  188.       if (actWindow->needpositiongui) {
  189.     actWindow->needpositiongui = FALSE;
  190.     actWindow->fullscreen = FALSE;        /* BUG?: could prevent fullscreen-mode */
  191.       }
  192.  
  193.       if (actWindow->needreshape) {
  194.     actWindow->needreshape = FALSE;
  195.     actWindow->needreshapegui = FALSE;                /* Reshaping and redisplaying is useless */
  196.     actWindow->needredisplay = FALSE;                /* this round. Change is inevitable */
  197.     /* Let the change be made through the gui */
  198.     ChangeWindowBox(win, actWindow->winx, actWindow->winy, actWindow->winwidth, actWindow->winheight);
  199.     actWindow->fullscreen = FALSE;        /* BUG?: could prevent fullscreen-mode */
  200.       }
  201.  
  202.       if (actWindow->needreshapegui) {
  203.     actWindow->needreshapegui = FALSE;
  204.     if (actWindow->reshapefunc)
  205.       (*actWindow->reshapefunc) (InnerWidth(win), InnerHeight(win));
  206.     actWindow->fullscreen = FALSE;        /* BUG?: could prevent fullscreen-mode */
  207.       }
  208.  
  209.       if (actWindow->fullscreen) {
  210.        /*
  211.         * TODO: make real fullscreen
  212.         *  close window, open borderless window on old screen, rearrange contexts
  213.         *  pop the window to front if something overlays it
  214.         * ALTERNATIVE:
  215.         *  try to make window borderless on the run
  216.         */
  217.     ChangeWindowBox(win, actWindow->winx = 0,
  218.                  actWindow->winy = 0,
  219.                  actWindow->winwidth = win->WScreen->Width,
  220.                  actWindow->winheight = win->WScreen->Height);
  221.     WindowToFront(win);
  222.       }
  223.  
  224.       if (actWindow->needredisplay) {
  225.     actWindow->needredisplay = FALSE;
  226.     if (actWindow->displayfunc)
  227.       (*actWindow->displayfunc) ();
  228.       }
  229.  
  230.       if (actWindow->needvisibility) {
  231.     actWindow->needvisibility = FALSE;
  232.     if (actWindow->visibilityfunc)
  233.       (*actWindow->visibilityfunc) (actWindow->visible ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
  234.       }
  235.  
  236.       if ((actWindow->leftmenu && actWindow->leftmenu->needupdate) || actWindow->needleftmenu) {
  237.     actWindow->needleftmenu = FALSE;
  238.     RedoMenu(GLUT_LEFT_BUTTON, actWindow->leftmenu);
  239.       }
  240.  
  241.       if ((actWindow->middlemenu && actWindow->middlemenu->needupdate) || actWindow->needmiddlemenu) {
  242.     actWindow->needmiddlemenu = FALSE;
  243.     RedoMenu(GLUT_MIDDLE_BUTTON, actWindow->middlemenu);
  244.       }
  245.  
  246.       if ((actWindow->rightmenu && actWindow->rightmenu->needupdate) || actWindow->needrightmenu) {
  247.     actWindow->needrightmenu = FALSE;
  248.     RedoMenu(GLUT_RIGHT_BUTTON, actWindow->rightmenu);
  249.       }
  250.     }
  251.  
  252.     if (glutstuff.Menues.nodes) {
  253.       actMenu = (struct GlutMenu *)&glutstuff.Menues;
  254.       while ((actMenu = (struct GlutMenu *)nGetNext(&actMenu->MenuNode))) {
  255.     stuffMakeCurrentMenu(actMenu);
  256.     actMenu->needupdate = FALSE;
  257.       }
  258.     }
  259.  
  260.     /* Wait for something to happen
  261.      */
  262.     if (glutstuff.idlefunc == NULL)
  263.       Wait(1L << glutstuff.msgport->mp_SigBit);
  264.  
  265.     /* Handle all messages (if any)
  266.      */
  267.     while ((msg = (struct IntuiMessage *)GetMsg(glutstuff.msgport))) {
  268.       struct GlutMenuEntry *actEntry;
  269.       struct MenuItem *item;
  270.       UWORD menuNumber;
  271.       struct IntuiMessage cmsg = *msg;
  272.  
  273.       ReplyMsg(&msg->ExecMessage);
  274.  
  275.       stuffMakeCurrent((struct GlutWindow *)cmsg.IDCMPWindow->UserData);
  276.       if (glutstuff.curwin != (struct GlutWindow *)cmsg.IDCMPWindow->UserData) {
  277.         Printf("serious error found in stuffMakeCurrent(), quitting ...\n");
  278.         continue;
  279.       }
  280.       actWindow = glutstuff.curwin;
  281.  
  282.       if (actWindow->window != cmsg.IDCMPWindow) {
  283.         Printf("serious error found in stuffMakeCurrent(), quitting ...\n");
  284.         continue;
  285.       }
  286.       win = actWindow->window;
  287.  
  288.       actWindow->qualifiers = cmsg.Qualifier;
  289.       switch (cmsg.Class) {
  290.     case IDCMP_REFRESHWINDOW:                            /* received only in DB-mode, non-DB-modes are NoCareRefresh */
  291.       BeginRefresh(win);
  292.       amigaMesaSwapBuffers(actWindow->context);                    /* put current contents into damaged region */
  293.       EndRefresh(win, TRUE);
  294.       break;
  295.     case IDCMP_CHANGEWINDOW:
  296.       idleing = FALSE;
  297.       actWindow->winx = win->LeftEdge;
  298.       actWindow->winy = win->TopEdge;
  299.       actWindow->winwidth = InnerWidth(win);
  300.       actWindow->winheight = InnerHeight(win);
  301.       if ((InnerWidth(win) != actWindow->wincurwidth) ||
  302.           (InnerHeight(win) != actWindow->wincurheight)) {
  303. #ifdef USE_CLIP_LAYER_
  304.         if (actWindow->clipreg)                            /* Get rid of last clipping region */
  305.           DisposeRegion(InstallClipRegion(win->WLayer, NULL));
  306.         clipWindowToBorders(win);
  307. #endif
  308.         actWindow->wincurwidth = InnerWidth(win);
  309.         actWindow->wincurheight = InnerHeight(win);
  310.         actWindow->needreshapegui = TRUE;
  311.         actWindow->needredisplay = TRUE;
  312.       }
  313.       if ((win->LeftEdge != actWindow->wincurx) ||
  314.           (win->TopEdge != actWindow->wincury)) {
  315.         actWindow->wincurx = win->LeftEdge;
  316.         actWindow->wincury = win->TopEdge;
  317.         actWindow->needpositiongui = TRUE;
  318.       }
  319.       break;
  320.     case IDCMP_VANILLAKEY:
  321.       if (cmsg.Code & IECODE_UP_PREFIX) {
  322.         if (actWindow->keyboardupfunc) {
  323.           if (!((cmsg.Qualifier & IEQUALIFIER_REPEAT) &&
  324.             (actWindow->ignorekeyrepeat ||
  325.              (actWindow->repeatmode == GLUT_KEY_REPEAT_OFF)))) {
  326.             idleing = FALSE;
  327.             (*actWindow->keyboardupfunc) (ConvRaw(cmsg.Code, cmsg.Qualifier), cmsg.MouseX, cmsg.MouseY);
  328.           }
  329.         }
  330.       }
  331.       else if (actWindow->keyboardfunc) {
  332.         if (!((cmsg.Qualifier & IEQUALIFIER_REPEAT) &&
  333.           (actWindow->ignorekeyrepeat ||
  334.            (actWindow->repeatmode == GLUT_KEY_REPEAT_OFF)))) {
  335.           idleing = FALSE;
  336.           (*actWindow->keyboardfunc) (ConvRaw(cmsg.Code, cmsg.Qualifier), cmsg.MouseX, cmsg.MouseY);
  337.         }
  338.       }
  339.       break;
  340.     case IDCMP_RAWKEY:
  341.       if (cmsg.Code & IECODE_UP_PREFIX) {
  342.         if (actWindow->specialupfunc) {
  343.           if (!((cmsg.Qualifier & IEQUALIFIER_REPEAT) &&
  344.             (actWindow->ignorekeyrepeat ||
  345.              (actWindow->repeatmode == GLUT_KEY_REPEAT_OFF)))) {
  346.             idleing = FALSE;
  347.             (*actWindow->specialupfunc) (ConvRaw(cmsg.Code, cmsg.Qualifier), cmsg.MouseX, cmsg.MouseY);
  348.           }
  349.         }
  350.       }
  351.       else if (actWindow->specialfunc) {
  352.         if (!((cmsg.Qualifier & IEQUALIFIER_REPEAT) &&
  353.           (actWindow->ignorekeyrepeat ||
  354.            (actWindow->repeatmode == GLUT_KEY_REPEAT_OFF)))) {
  355.           idleing = FALSE;
  356.           (*actWindow->specialfunc) (ConvRaw(cmsg.Code, cmsg.Qualifier), cmsg.MouseX, cmsg.MouseY);
  357.         }
  358.       }
  359.       break;
  360.     case IDCMP_MENUPICK:
  361.       menuNumber = cmsg.Code;
  362.       while (menuNumber != MENUNULL) {
  363.         item = ItemAddress(actWindow->menu, menuNumber);
  364.         actEntry = (struct GlutMenuEntry *)GTMENUITEM_USERDATA(item);
  365.         stuffMakeCurrentMenu(actEntry->EntryMenu);
  366.         if (glutstuff.curmenu->menufunc) {
  367.           idleing = FALSE;
  368.           (*glutstuff.curmenu->menufunc) (actEntry->EntryValue);
  369.         }
  370.         menuNumber = item->NextSelect;
  371.       }
  372.       break;
  373.     case IDCMP_CLOSEWINDOW:
  374.       if (wanttoquit) {
  375.         /* User wants to quit, but ESC doesn't do anything
  376.          * Panic, and return in the hope that it will drop
  377.          * through to an end-of-program call.
  378.          * (Note that we don't use exit(), as we may want
  379.          * to put all this in a run-time library).
  380.          */
  381.         return;
  382.       }
  383.       if (actWindow->keyboardfunc) {
  384.         idleing = FALSE;
  385.         (*actWindow->keyboardfunc) (27, 0, 0);
  386.       }
  387.       wanttoquit = TRUE;
  388.       break;
  389.     case IDCMP_MOUSEBUTTONS:
  390.       if (actWindow->mousefunc) {
  391.         idleing = FALSE;
  392.         (*actWindow->mousefunc) (ConvToButton(cmsg.Code, cmsg.Qualifier), ConvToButtonState(cmsg.Code), cmsg.MouseX, cmsg.MouseY);
  393.       }
  394.       break;
  395.     case IDCMP_INTUITICKS:
  396.       if ((actWindow->mousex != cmsg.MouseX) ||
  397.           (actWindow->mousey != cmsg.MouseY)) {
  398.         actWindow->mousex = cmsg.MouseX;
  399.         actWindow->mousey = cmsg.MouseY;
  400.  
  401.         if ((cmsg.Qualifier & IEQUALIFIER_LEFTBUTTON) &&
  402.         (actWindow->motionfunc)) {
  403.           idleing = FALSE;
  404.           (*actWindow->motionfunc) (cmsg.MouseX, cmsg.MouseY);
  405.         }
  406.         else if (actWindow->passivemotionfunc) {
  407.           idleing = FALSE;
  408.           (*actWindow->passivemotionfunc) (cmsg.MouseX, cmsg.MouseY);
  409.         }
  410.  
  411.         if (actWindow->entryfunc) {
  412.           if ((actWindow->mousex < actWindow->winx) ||
  413.           (actWindow->mousey < actWindow->winy) ||
  414.           (actWindow->mousex > (actWindow->winx + win->Width)) ||
  415.           (actWindow->mousey > (actWindow->winy + win->Height))) {
  416.             /* out of window region */
  417.             if (!actWindow->lastoutwindow) {
  418.           idleing = FALSE;
  419.               (*actWindow->entryfunc) (GLUT_LEFT);
  420.               actWindow->lastoutwindow = TRUE;
  421.             }
  422.           }
  423.           else {
  424.             /* in to window region */
  425.             if (actWindow->lastoutwindow) {
  426.           idleing = FALSE;
  427.               (*actWindow->entryfunc) (GLUT_ENTERED);
  428.               actWindow->lastoutwindow = FALSE;
  429.             }
  430.           }
  431.         }
  432.       }
  433.       break;
  434.       }
  435.     }
  436.  
  437. #if 0    
  438.     if (actWindow->windowstatusfunc) {
  439.       struct GlutWindow *gwo;
  440.       
  441.       for (gwo = (struct GlutWindow *)nGetHead(&glutstuff.Windows); gwo; gwo = (struct GlutWindow *)nGetNext(&gwo->WindowNode)) {
  442.         /* skip us, compare only others */
  443.         if(gwo != actWindow) {
  444.           /* ... dynamic rectangle list */
  445.         }
  446.       }
  447.     }
  448. #endif
  449.  
  450.     /* If nothing is happening, call the idle function
  451.      */
  452.     if (idleing && glutstuff.idlefunc)
  453.       (*glutstuff.idlefunc) ();
  454.   }
  455. }
  456.